package com.nbcio.modules.erp.doc.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nbcio.modules.erp.doc.domain.ErpBill;
import com.nbcio.modules.erp.doc.mapper.ErpBillMapper;
import com.nbcio.modules.erp.doc.service.IErpBillService;
import com.nbcio.modules.erp.inventory.service.IErpInventoryService;
import com.nbcio.workflow.service.WfCommonService;
import com.nbcio.workflow.service.IWfProcessService;
import com.nbcio.workflow.service.WfCallBackServiceI;
import com.nbcio.workflow.domain.WfMyBusiness;
import com.nbcio.workflow.mapper.WfDeployFormMapper;
import com.nbcio.workflow.domain.WfDeployForm;
import com.nbcio.common.core.domain.R;
import com.nbcio.common.satoken.utils.LoginHelper;
import jakarta.annotation.Resource;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("erpBillService")
public class ErpBillServiceImpl extends ServiceImpl<ErpBillMapper, ErpBill> implements IErpBillService, WfCallBackServiceI {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private IErpInventoryService inventoryService;
    @Resource
    private WfCommonService wfCommonService;
    @Resource
    private IWfProcessService wfProcessService;
    @Resource
    private WfDeployFormMapper wfDeployFormMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submit(String billIdStr) {
        Long billId = Long.parseLong(billIdStr);
        ErpBill bill = this.getById(billId);
        if (bill == null) return false;
        bill.setStatus("SUBMITTED");
        bill.setSubmitTime(LocalDateTime.now());
        this.updateById(bill);
        
        // 通过 formKey 查找流程定义（formKey 与业务类型对应）
        String formKey = switch (bill.getBillType()) {
            case "PO_IN" -> "erp_po_in_approve";
            case "SO_OUT" -> "erp_so_out_approve";
            default -> "erp_generic_approve";
        };
        
        // 通过 formKey 查询流程部署表单关联，获取 deployId
        WfDeployForm deployForm = wfDeployFormMapper.selectSysDeployFormByFormId(formKey);
        ProcessDefinition processDefinition = null;
        
        if (deployForm != null && deployForm.getDeployId() != null) {
            // 通过 deployId 查询流程定义
            processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(deployForm.getDeployId())
                    .latestVersion()
                    .singleResult();
        }
        
        // 如果通过 deployForm 没找到，尝试直接用 formKey 作为 processKey 查询（向后兼容）
        if (processDefinition == null) {
            processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey(formKey)
                    .latestVersion()
                    .singleResult();
        }
        
        if (processDefinition != null) {
            // 流程定义存在，使用现有流程模块启动流程
            try {
                // 初始化业务与流程的关联
                String title = bill.getBillType() + "-" + bill.getBillNo();
                String routeName = bill.getBillType().equals("PO_IN") ? "/erp/po-in/edit" : "/erp/so-out/edit";
                boolean initSuccess = wfCommonService.initActBusiness(
                    title, 
                    String.valueOf(bill.getBillId()), 
                    "erpBillService",
                    processDefinition.getKey(), 
                    processDefinition.getId(),
                    routeName
                );
                
                if (initSuccess) {
                    // 启动流程实例
                    Map<String, Object> vars = new HashMap<>();
                    vars.put("billId", bill.getBillId());
                    vars.put("billType", bill.getBillType());
                    vars.put("billNo", bill.getBillNo());
                    R<Void> result = wfProcessService.startProcessByDefKey(processDefinition.getKey(), vars);
                    if (result.getCode() == 200) {
                        bill.setStatus("APPROVING");
                    } else {
                        bill.setStatus("SUBMITTED");
                    }
                } else {
                    // 初始化失败，跳过审批流程
                    bill.setStatus("APPROVED");
                    bill.setApproveTime(LocalDateTime.now());
                }
            } catch (Exception e) {
                // 启动流程失败，跳过审批流程
                bill.setStatus("APPROVED");
                bill.setApproveTime(LocalDateTime.now());
            }
        } else {
            // 流程定义不存在，跳过审批流程，直接设置为已审批
            bill.setStatus("APPROVED");
            bill.setApproveTime(LocalDateTime.now());
        }
        
        return this.updateById(bill);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean approve(String billIdStr) {
        Long billId = Long.parseLong(billIdStr);
        ErpBill bill = this.getById(billId);
        if (bill == null) return false;
        bill.setStatus("APPROVED");
        bill.setApproveTime(LocalDateTime.now());
        return this.updateById(bill);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean post(String billIdStr) {
        Long billId = Long.parseLong(billIdStr);
        ErpBill bill = this.getById(billId);
        if (bill == null) return false;
        if (!"APPROVED".equals(bill.getStatus())) {
            throw new RuntimeException("单据未审批通过，无法过账");
        }
        // 过账逻辑（生成库存事务与台账、财务凭证）
        inventoryService.postBill(bill);
        bill.setStatus("POSTED");
        return this.updateById(bill);
    }

    // ========== 实现流程回调接口 WfCallBackServiceI ==========
    
    @Override
    public void afterFlowHandle(WfMyBusiness business) {
        // 流程处理完成后的回调
        String dataId = business.getDataId();
        String actStatus = business.getActStatus();
        
        if (dataId == null || dataId.isEmpty()) {
            return;
        }
        
        try {
            Long billId = Long.parseLong(dataId);
            ErpBill bill = this.getById(billId);
            if (bill == null) {
                return;
            }
            
            // 根据流程状态更新单据状态
            if ("审批通过".equals(actStatus) || "approved".equalsIgnoreCase(actStatus)) {
                bill.setStatus("APPROVED");
                bill.setApproveTime(LocalDateTime.now());
                this.updateById(bill);
            } else if ("驳回".equals(actStatus) || "rejected".equalsIgnoreCase(actStatus)) {
                bill.setStatus("REJECTED");
                this.updateById(bill);
            } else if ("撤回".equals(actStatus) || "revoke".equalsIgnoreCase(actStatus)) {
                bill.setStatus("DRAFT");
                this.updateById(bill);
            }
        } catch (Exception e) {
            // 忽略转换错误
        }
    }

    @Override
    public Object getBusinessDataById(String dataId) {
        // 根据业务id返回业务表单数据
        try {
            Long billId = Long.parseLong(dataId);
            return this.getById(billId);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public Map<String, Object> flowValuesOfTask(String taskNameId, Map<String, Object> values) {
        // 返回当前节点的流程变量（可自定义扩展）
        return values;
    }

    @Override
    public List<String> flowCandidateUsernamesOfTask(String taskNameId, Map<String, Object> values) {
        // 返回当前节点的候选人username（可自定义扩展）
        return null;
    }
}


